import sys
import os
from PyQt6.QtWidgets import (QApplication, QMainWindow, QPushButton, QVBoxLayout,
                             QWidget, QListWidget, QLabel, QFileDialog,
                             QProgressBar, QMessageBox, QLineEdit, QHBoxLayout,
                             QInputDialog, QSystemTrayIcon, QMenu, QStyle)
from PyQt6.QtCore import Qt, QMimeData
from PyQt6.QtGui import QIcon, QAction
from network_handler import NetworkHandler
import winreg

class FileTransferWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("局域网文件传输")
        self.setGeometry(100, 100, 600, 400)
        
        # 设置窗口图标
        icon_path = self.get_icon_path()
        if icon_path:
            self.setWindowIcon(QIcon(icon_path))
        
        # 设置开机自启
        self.set_auto_start()
        
        # 设置托盘图标
        self.setup_tray_icon()
        
        # 创建主窗口部件
        main_widget = QWidget()
        self.setCentralWidget(main_widget)
        layout = QVBoxLayout()
        
        # 名称输入区域
        name_layout = QHBoxLayout()
        name_label = QLabel("设备名称:")
        self.name_input = QLineEdit()
        self.name_input.setPlaceholderText("请输入设备名称")
        # 尝试从配置文件读取上次使用的名称
        try:
            with open('device_name.txt', 'r') as f:
                self.name_input.setText(f.read().strip())
        except:
            pass
        name_layout.addWidget(name_label)
        name_layout.addWidget(self.name_input)
        layout.addLayout(name_layout)
        
        # 广播查询按钮
        self.scan_button = QPushButton("扫描局域网设备")
        self.scan_button.clicked.connect(self.scan_network)
        layout.addWidget(self.scan_button)
        
        # 在设备列表之前添加手动添加IP的按钮
        add_ip_layout = QHBoxLayout()
        self.add_ip_button = QPushButton("手动添加IP")
        self.add_ip_button.clicked.connect(self.add_ip_manually)
        add_ip_layout.addWidget(self.add_ip_button)
        layout.addLayout(add_ip_layout)
        
        # 设备列表
        self.device_list = QListWidget()
        layout.addWidget(QLabel("可用设备:"))
        layout.addWidget(self.device_list)
        
        # 加载保存的设备列表
        self.load_saved_devices()
        
        # 文件拖放区域
        self.file_label = QLabel("将文件拖到这里或点击选择文件")
        self.file_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.file_label.setStyleSheet("""
            QLabel {
                border: 2px dashed #aaa;
                border-radius: 5px;
                padding: 20px;
                background: #f0f0f0;
            }
        """)
        self.file_label.setAcceptDrops(True)
        self.file_label.mousePressEvent = self.select_file
        layout.addWidget(self.file_label)
        
        # 进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setVisible(False)
        layout.addWidget(self.progress_bar)
        
        # 传输按钮
        self.transfer_button = QPushButton("传输文件")
        self.transfer_button.clicked.connect(self.transfer_file)
        layout.addWidget(self.transfer_button)
        
        main_widget.setLayout(layout)
        
        # 初始化网络处理器
        self.network_handler = NetworkHandler()
        self.selected_file = None
        
        # 连接信号
        self.network_handler.progress_updated.connect(self.update_progress)
        self.network_handler.transfer_completed.connect(self.show_completion_dialog)
        self.network_handler.transfer_error.connect(self.show_error_dialog)
        
    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()
            
    def dropEvent(self, event):
        files = [u.toLocalFile() for u in event.mimeData().urls()]
        if files:
            self.selected_file = files[0]
            self.file_label.setText(f"已选择文件: {os.path.basename(self.selected_file)}")
            
    def select_file(self, event):
        file_name, _ = QFileDialog.getOpenFileName(self, "选择文件")
        if file_name:
            self.selected_file = file_name
            self.file_label.setText(f"已选择文件: {os.path.basename(self.selected_file)}")
            
    def scan_network(self):
        """扫描网络设备"""
        # 保存当前的手动添加的设备
        saved_devices = []
        for i in range(self.device_list.count()):
            item_text = self.device_list.item(i).text()
            saved_devices.append(item_text)
        
        # 清空列表并扫描
        self.device_list.clear()
        
        # 首先添加保存的设备
        for device_text in saved_devices:
            self.device_list.addItem(device_text)
        
        # 然后扫描新设备
        device_name = self.name_input.text().strip()
        if device_name:
            try:
                with open('device_name.txt', 'w') as f:
                    f.write(device_name)
            except:
                pass
        devices = self.network_handler.scan_network(device_name)
        for device_info in devices:
            device_text = f"{device_info['name']} ({device_info['ip']})"
            # 检查是否已存在
            existing_items = [self.device_list.item(i).text() 
                            for i in range(self.device_list.count())]
            if device_text not in existing_items:
                self.device_list.addItem(device_text)
    
    def transfer_file(self):
        if not self.selected_file:
            QMessageBox.warning(self, "错误", "请先选择要传输的文件")
            return
        selected_items = self.device_list.selectedItems()
        if not selected_items:
            QMessageBox.warning(self, "错误", "请选择目标设备")
            return
            
        # 从文本中提取IP地址
        item_text = selected_items[0].text()
        target_ip = item_text[item_text.rfind('(') + 1:item_text.rfind(')')]
        
        # 显示进度条并设置初始值
        self.progress_bar.setVisible(True)
        self.progress_bar.setValue(0)
        
        # 开始传输
        self.network_handler.send_file(self.selected_file, target_ip)
        
    def update_progress(self, value):
        """更新进度条"""
        self.progress_bar.setVisible(True)
        self.progress_bar.setValue(value)
        if value >= 100:
            self.progress_bar.setVisible(False)
            
    def show_completion_dialog(self, file_path):
        """显示传输完成对话框"""
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Icon.Information)
        msg.setWindowTitle("传输完成")
        msg.setText(f"文件已保存到:\n{file_path}")
        msg.setStandardButtons(QMessageBox.StandardButton.Ok)
        
        # 添加打开文件夹按钮
        open_button = msg.addButton("打开文件夹", QMessageBox.ButtonRole.ActionRole)
        
        msg.exec()
        
        # 如果点击了打开文件夹按钮
        if msg.clickedButton() == open_button:
            self.network_handler.open_file_location(file_path)
    
    def add_ip_manually(self):
        """手动添加IP地址"""
        dialog = QInputDialog(self)
        dialog.setWindowTitle("添加设备")
        dialog.setLabelText("请输入设备IP地址:")
        dialog.setInputMode(QInputDialog.InputMode.TextInput)
        
        if dialog.exec() == QInputDialog.DialogCode.Accepted:
            ip = dialog.textValue().strip()
            # 简单的IP地址格式验证
            if self.is_valid_ip(ip):
                # 添加到设备列表
                name_dialog = QInputDialog(self)
                name_dialog.setWindowTitle("设备名称")
                name_dialog.setLabelText("请输入设备名称(可选):")
                name_dialog.setInputMode(QInputDialog.InputMode.TextInput)
                
                device_name = "未命名设备"
                if name_dialog.exec() == QInputDialog.DialogCode.Accepted:
                    input_name = name_dialog.textValue().strip()
                    if input_name:
                        device_name = input_name
                
                # 检查是否已存在
                existing_items = [self.device_list.item(i).text() for i in range(self.device_list.count())]
                device_text = f"{device_name} ({ip})"
                if device_text not in existing_items:
                    self.device_list.addItem(device_text)
                    # 保存新添加的设备
                    self.save_devices()
            else:
                QMessageBox.warning(self, "错误", "请输入有效的IP地址")
    
    def is_valid_ip(self, ip):
        """验证IP地址格式"""
        try:
            parts = ip.split('.')
            return len(parts) == 4 and all(0 <= int(part) <= 255 for part in parts)
        except:
            return False
    
    def show_error_dialog(self, error_message):
        """显示错误对话框"""
        QMessageBox.critical(self, "传输错误", error_message)
        self.progress_bar.setVisible(False)
        self.progress_bar.setValue(0)
    
    def save_devices(self):
        """保存设备列表到文件"""
        devices = []
        for i in range(self.device_list.count()):
            item_text = self.device_list.item(i).text()
            # 解析设备名称和IP
            name = item_text[:item_text.rfind('(')].strip()
            ip = item_text[item_text.rfind('(') + 1:item_text.rfind(')')]
            devices.append({'name': name, 'ip': ip})
        
        try:
            with open('saved_devices.txt', 'w', encoding='utf-8') as f:
                for device in devices:
                    f.write(f"{device['name']},{device['ip']}\n")
        except Exception as e:
            print(f"保存设备列表时出错: {str(e)}")
    
    def load_saved_devices(self):
        """从文件加载保存的设备列表"""
        try:
            with open('saved_devices.txt', 'r', encoding='utf-8') as f:
                for line in f:
                    line = line.strip()
                    if line:
                        name, ip = line.split(',')
                        device_text = f"{name} ({ip})"
                        # 检查是否已存在
                        existing_items = [self.device_list.item(i).text() 
                                        for i in range(self.device_list.count())]
                        if device_text not in existing_items:
                            self.device_list.addItem(device_text)
        except FileNotFoundError:
            # 文件不存在时忽略
            pass
        except Exception as e:
            print(f"加载设备列表时出错: {str(e)}")
    
    def setup_tray_icon(self):
        """设置系统托盘图标"""
        # 创建托盘图标
        self.tray_icon = QSystemTrayIcon(self)
        
        # 设置图标
        icon_path = self.get_icon_path()
        if icon_path:
            self.tray_icon.setIcon(QIcon(icon_path))
        else:
            # 如果没有找到图标文件，使用系统默认图标
            self.tray_icon.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_ComputerIcon))
        
        # 创建托盘菜单
        tray_menu = QMenu()
        
        # 添加显示/隐藏动作
        show_action = QAction("显示主窗口", self)
        show_action.triggered.connect(self.show)
        tray_menu.addAction(show_action)
        
        # 添加退出动作
        quit_action = QAction("退出", self)
        quit_action.triggered.connect(self.quit_application)
        tray_menu.addAction(quit_action)
        
        # 设置托盘菜单
        self.tray_icon.setContextMenu(tray_menu)
        
        # 设置托盘图标的提示文本
        self.tray_icon.setToolTip("局域网文件传输")
        
        # 显示托盘图标
        self.tray_icon.show()
        
        # 连接托盘图标的点击事件
        self.tray_icon.activated.connect(self.tray_icon_activated)
    
    def tray_icon_activated(self, reason):
        """处理托盘图标的点击事件"""
        if reason == QSystemTrayIcon.ActivationReason.DoubleClick:
            self.show()
            self.activateWindow()
    
    def closeEvent(self, event):
        """重写关闭事件，实现最小化到托盘"""
        event.ignore()  # 忽略关闭事件
        self.hide()     # 隐藏窗口
        
        # 显示提示气泡（可选）
        self.tray_icon.showMessage(
            "程序已最小化",
            "程序将在后台继续运行，双击托盘图标可以重新打开主界面",
            QSystemTrayIcon.MessageIcon.Information,
            2000  # 显示2秒
        )
    
    def quit_application(self):
        """完全退出应用程序"""
        QApplication.quit()
    
    def set_auto_start(self):
        """设置开机自启动"""
        try:
            # 获取当前执行文件的路径
            app_path = os.path.abspath(sys.argv[0])
            
            # 如果是 .py 文件，需要使用 pythonw 来启动
            if app_path.endswith('.py'):
                app_path = f'pythonw "{app_path}"'
            
            # 注册表项名称
            app_name = "FileTransfer"
            
            try:
                # 先尝试打开注册表项检查是否已经设置了自启动
                key = winreg.OpenKey(
                    winreg.HKEY_CURRENT_USER,
                    r"Software\Microsoft\Windows\CurrentVersion\Run",
                    0,
                    winreg.KEY_READ
                )
                try:
                    current_value = winreg.QueryValueEx(key, app_name)[0]
                    winreg.CloseKey(key)
                    if current_value == app_path:
                        # 已经设置了自启动，不需要再设置
                        return
                except WindowsError:
                    # 键不存在，需要设置
                    winreg.CloseKey(key)
            except WindowsError:
                pass
            
            # 询问用户是否设置开机自启
            reply = QMessageBox.question(
                self,
                "开机自启动",
                "是否将程序设置为开机自动启动？",
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
            )
            
            if reply == QMessageBox.StandardButton.Yes:
                try:
                    # 打开注册表项
                    key = winreg.OpenKey(
                        winreg.HKEY_CURRENT_USER,
                        r"Software\Microsoft\Windows\CurrentVersion\Run",
                        0,
                        winreg.KEY_SET_VALUE | winreg.KEY_READ
                    )
                    
                    # 设置自启动
                    winreg.SetValueEx(key, app_name, 0, winreg.REG_SZ, app_path)
                    winreg.CloseKey(key)
                    
                    # 设置成功提示
                    QMessageBox.information(
                        self,
                        "成功",
                        "已成功设置开机自启动"
                    )
                    
                except Exception as e:
                    print(f"设置开机自启动时出错: {str(e)}")
                    # 显示详细的错误信息
                    QMessageBox.warning(
                        self,
                        "警告",
                        f"设置开机自启动失败：\n{str(e)}\n\n请以管理员身份运行程序"
                    )
                    
        except Exception as e:
            print(f"检查开机自启动设置时出错: {str(e)}")
    
    def get_icon_path(self):
        """获取图标文件路径"""
        # 尝试多个可能的位置
        possible_paths = [
            "file_transfer.ico",  # 当前目录
            os.path.join(os.path.dirname(sys.executable), "file_transfer.ico"),  # exe所在目录
            os.path.join(os.path.dirname(__file__), "file_transfer.ico"),  # 脚本所在目录
        ]
        
        for path in possible_paths:
            if os.path.exists(path):
                return path
        return None

if __name__ == '__main__':
    # 确保只运行一个实例
    from PyQt6.QtNetwork import QLocalSocket, QLocalServer
    
    app = QApplication(sys.argv)
    
    # 检查是否已经有实例在运行
    socket = QLocalSocket()
    socket.connectToServer("FileTransferApp")
    if socket.waitForConnected(500):
        # 如果能连接上，说明已经有实例在运行
        socket.close()
        sys.exit(0)
    else:
        # 创建服务器
        server = QLocalServer()
        server.listen("FileTransferApp")
    
    # 创建并显示主窗口
    window = FileTransferWindow()
    window.show()
    sys.exit(app.exec()) 